/*****************************************************************
Copyright (c) 2011 - 2017 Qualcomm Technologies International, Ltd.

PROJECT
    source
    
FILE NAME
    source_button_handler.c

DESCRIPTION
    Handles button events.
    The functionality is only included if INCLUDE_BUTTONS is defined.
    
*/


#ifdef INCLUDE_BUTTONS

/* header for this file */
#include "source_button_handler.h"
/* application header files */
#include "source_app_msg_handler.h"
#include "source_debug.h" 
#include "source_audio.h"
#include "source_power.h"
#include "source_a2dp.h"
#include "source_states.h"
#include "source_avrcp.h"
#include "source_connection_mgr.h"
#include "source_led_handler.h"
#include "source_private.h"
#include "source_ps.h"
#include "source_usb.h"
#include "system.h"
#include "power_manager_conditions.h"
#include "charger_monitor.h"
#include "power_manager.h"
#include "battery_monitor.h"
#include <system_reboot.h>
/* profile/library headers */
#include <boot.h>
#include <logging.h>
/* VM headers */
#include <psu.h>

#ifdef DEBUG_BUTTONS
    #define BUTTONS_DEBUG(x) SOURCE_DEBUG(x)
#else
    #define BUTTONS_DEBUG(x)
#endif

/* structure holding the button data */
typedef struct
{
    TaskData buttonTask;
    PioState pio_state;
    bool volUpState;
    bool volDownState;
    uint32 factoryResetTime;
    unsigned power_button_released:1;
} BUTTON_DATA_T;

static BUTTON_DATA_T BUTTON_RUNDATA;
/****************************************************************************
NAME    
    HandleButtonMsgInquiry - Enters Inquiry mode from button event
*/ 

static void HandleButtonMsgPairing(void)
{
    switch (states_get_state())
    {
        case SOURCE_STATE_IDLE:      
        case SOURCE_STATE_CONNECTABLE:
        case SOURCE_STATE_DISCOVERABLE:
        case SOURCE_STATE_CONNECTING:
        {
            /* cancel connecting timer */
            MessageCancelAll(app_get_instance(), APP_CONNECT_REQ);
            /* indicate this is a forced inquiry, and must remain in this state until a successful connection */
            inquiry_set_forced_inquiry_mode(TRUE);
            /* move to inquiry state */
            states_set_state(SOURCE_STATE_INQUIRING);
        }
        break;

        case SOURCE_STATE_CONNECTED:
        {
#ifdef INCLUDE_DUALSTREAM
            /*if(BdaddrIsZero(&theSource->app_data.bt1_addr) || BdaddrIsZero(&theSource->app_data.bt2_addr))*/
            /* cancel connecting timer */
            MessageCancelAll(app_get_instance(), APP_CONNECT_REQ);
            /* indicate this is a forced inquiry, and must remain in this state until a successful connection */
            inquiry_set_forced_inquiry_mode(TRUE);

            states_set_state(SOURCE_STATE_INQUIRING);
#else
            /* cancel connecting timer */
            MessageCancelAll(app_get_instance(), APP_CONNECT_REQ);
            /* indicate this is a forced inquiry, and must remain in this state until a successful connection */
            inquiry_set_forced_inquiry_mode(TRUE);
            /* make sure audio is suspend */
            if(audio_is_routable())
            {
                /* move to inquiry state */
                states_set_state(SOURCE_STATE_INQUIRING);
            }
            else
            {
                MessageSend(app_get_instance(), APP_AUDIO_SUSPEND, 0);
            }
#endif
        }
        break;
        
        default:
        {

        }
        break;
    }
}

static void HandleButtonMsgAuxConnectionChange(void)
{
    MessageCancelAll(app_get_instance(), APP_UPDATE_AUDIO_ROUTING);

    MessageSendLater(app_get_instance(), APP_UPDATE_AUDIO_ROUTING, 0, 1000);
}

static void HandleButtonMsgPairingCancel(void)
{
    if(states_get_state() == SOURCE_STATE_INQUIRING)
    {
        if(!connection_msg_pairing_list_empty())
        {
            /* Finish any ongoing inquiry */
            inquiry_complete();

            inquiry_set_forced_inquiry_mode(FALSE);

            if(a2dp_get_number_connections())
            {
                states_set_state(SOURCE_STATE_CONNECTED);

                MessageSend(app_get_instance(), APP_CODEC_LED_UPDATE, 0);
            }
            else
            {
                connection_mgr_start_connection_attempt(NULL, PROFILE_AGHFP , 0);
            }
        }
    }
}

static void HandleButtonMsgShowBattLevel(void)
{
    if((states_get_state() != SOURCE_STATE_INITIALISING) && (states_get_state() != SOURCE_STATE_POWERED_OFF))
    {
        if(!Charger_IsConnected())
        {
            power_show_battery_level_normal();
        }
    }
}

static void HandleButtonMsgVolumeChange(bool volumeUp)
{
    if(volumeUp)
    {
        MessageSend(app_get_instance(), APP_VOL_UP, 0);
    }
    else
    {
        MessageSend(app_get_instance(), APP_VOL_DOWN, 0);
    }
}

static void HandleButtonMsgFactoryReset(void)
{
    uint32 time = VmGetClock();

    if((time - BUTTON_RUNDATA.factoryResetTime) < 1000)
    {
        if(states_get_state() != SOURCE_STATE_POWERED_OFF)
        {
            leds_show_event(LED_EVENT_FACTORY_RESET);
        }
    }

    BUTTON_RUNDATA.factoryResetTime = time;
}

static void HandleButtonMsgNextTrack(void)
{
    MessageSend(app_get_instance(), APP_NEXT_TRACK, 0);
}

static void HandleButtonMsgPreviousTrack(void)
{
    MessageSend(app_get_instance(), APP_PREVIOUS_TRACK, 0);
}

static void HandleButtonMsgPower(void)
{
    if(PioGet32Bank(0) & PIO_SYS_CTRL)
    {
        if(states_get_state() == SOURCE_STATE_POWERED_OFF)
        {
            if(appPowerNeedsToPowerOff() &&
              (PowerGetTaskData()->state == POWER_STATE_INIT || PowerGetTaskData()->state == POWER_STATE_OK))
            {
                return;
            }

            states_set_state(SOURCE_STATE_IDLE);
        }
    }
    else
    {
        states_set_state(SOURCE_STATE_POWERED_OFF);
    }
}

static void HandleButtonMsgPlayPause(void)
{
    if(states_get_state() == SOURCE_STATE_CONNECTED)
    {
        usbHidSendMediaCommand(USB_HID_MEDIA_PLAY_PAUSE);
    }
    else if(states_get_state() == SOURCE_STATE_INQUIRING)
    {
        if(!connection_msg_pairing_list_empty())
        {
            /* Finish any ongoing inquiry */
            inquiry_complete();

            inquiry_set_forced_inquiry_mode(FALSE);

            if(a2dp_get_number_connections())
            {
                states_set_state(SOURCE_STATE_CONNECTED);
            }
            else
            {
                connection_mgr_start_connection_attempt(NULL, PROFILE_AGHFP , 0);
            }
        }
    }
}

static void HandleButtonMsgAudioCodecSwap(void)
{
    if(states_get_state() == SOURCE_STATE_CONNECTED)
    {
        MessageSendLater(app_get_instance(), APP_CODEC_SWITCH, 0, 800);
    }
}
/***************************************************************************
Functions
****************************************************************************
*/

/****************************************************************************
NAME    
    button_msg_handler - Message handler for button events
*/  
void button_msg_handler(Task task, MessageId id, Message message)
{
    UNUSED(task);
    UNUSED(message);
    BUTTONS_DEBUG(("button_msg_handler id = %d\n", id));
    switch (id)
    {
        case BUTTON_MSG_PAIRING:
        {
            DEBUG_LOG_INFO("BUTTON: BUTTON_MSG_PAIRING");
            HandleButtonMsgPairing();
        }
        break;

        case BUTTON_MSG_AUDIO_CODEC_SWAP:
        {
            DEBUG_LOG_INFO("BUTTON: BUTTON_MSG_AUDIO_CODEC_SWAP");
            HandleButtonMsgAudioCodecSwap();
        }
        break;
        
        case BUTTON_MSG_PLAY_PAUSE:
        {
            DEBUG_LOG_INFO("BUTTON: BUTTON_MSG_PLAY_PAUSE");
            HandleButtonMsgPlayPause();
        }
        break;

        case BUTTON_MSG_AUX_CONNECTION_CHANGE:
        {
            DEBUG_LOG_INFO("BUTTON: AUX_CONNECTION_CHANGE");
            HandleButtonMsgAuxConnectionChange();
        }
        break;

        case BUTTON_MSG_CANCEL_PAIRING:
        {
            HandleButtonMsgPairingCancel();
        }
        break;

        case BUTTON_MSG_FACTORY_RESET:
        {
            DEBUG_LOG_INFO("BUTTON: BUTTON_FACTORY_DEFAULT");
            HandleButtonMsgFactoryReset();
        }
        break;

        case BUTTON_MSG_VOL_UP:
        {
            DEBUG_LOG_INFO("BUTTON: BUTTON_MSG_VOL_UP");
            HandleButtonMsgVolumeChange(TRUE);
        }
        break;

        case BUTTON_MSG_VOL_DOWN:
        {
            DEBUG_LOG_INFO("BUTTON: BUTTON_MSG_VOL_DOWN");
            HandleButtonMsgVolumeChange(FALSE);
        }
        break;

        case BUTTON_MSG_NEXT_TRACK:
        {
            DEBUG_LOG_INFO("BUTTON: BUTTON_MSG_NEXT_TRACK");
            HandleButtonMsgNextTrack();
        }
        break;

        case BUTTON_MSG_PREVIOUS_TRACK:
        {
            DEBUG_LOG_INFO("BUTTON: BUTTON_MSG_PREVIOUS_TRACK");
            HandleButtonMsgPreviousTrack();
        }
        break;

        case BUTTON_MSG_POWER:
        {
            DEBUG_LOG_INFO("BUTTON: BUTTON_MSG_POWER");
            HandleButtonMsgPower();
        }
        break;

        case BUTTON_MSG_SHOW_BATT_LEVEL:
        {
            DEBUG_LOG_INFO("BUTTON: BUTTON_MSG_SHOW_BATT_LEVEL");
            HandleButtonMsgShowBattLevel();
        }
        break;

        default:
        {
            
        }
        break;
    }
}


/****************************************************************************
NAME    
    buttons_init - Initialises the button handling
*/ 
void buttons_init(void)
{
    memset(&BUTTON_RUNDATA,0,sizeof(BUTTON_DATA_T));
    BUTTON_RUNDATA.buttonTask.handler = button_msg_handler;
    
    pioInit(&BUTTON_RUNDATA.pio_state, &BUTTON_RUNDATA.buttonTask);
}

bool buttons_aux_cable_is_connected(void)
{
    return TRUE;
}

bool buttons_power_on(void)
{
    return PioGet32Bank(0) & PIO_SYS_CTRL;
}
#endif /* #INCLUDE_BUTTONS */

